﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SmokinAces.Object_Classes;
using SmokinAces.Object_Classes.Objects;

namespace SmokinAces
{
    public partial class Main_Engine : Microsoft.Xna.Framework.Game
    {
        public List<Sort_Delegate>[] Draw_Functions;
        public Game_Effect effect;
        //-----Draw Bounding Boxes
        public BasicEffect LineEffect;
        protected Color SelectionColor = Color.White;
        //------------------------------------------
        public BoundingBox CurrentScreen = new BoundingBox(new Vector3(3200.0f, 3200.0f, -1000.0f), new Vector3(3200.0f + 1024.0f, 3200.0f + 768.0f, 1000.0f));
        public List<Texture2D> Texture_List = new List<Texture2D>();
        protected HashSet<Update_Delegate> UpdateObjects = new HashSet<Update_Delegate>();
        protected Dictionary<String, Texture_List>[] Drawing_List;
        protected Dictionary<string, int> FileName_Int = new Dictionary<string, int>();
        protected List<Game_Object> GameObjects = new List<Game_Object>();
        protected List<Texture_List> DrawObjects = new List<Texture_List>();
        public SpriteFont GUIFont12;
        public SpriteFont GUIFont16;
        public SmokinAces.Object_Classes.Quadtree MapObjects;
        public SmokinAces.Object_Classes.Objects.Main_Character Hero;
        public int register_texture(string filename)
        {
            if (FileName_Int.ContainsKey(filename))
            {
                return FileName_Int[filename];
            }
            else
            {
                int index;

                Texture2D tempText = Texture2D.FromFile(GraphicsDevice, Content.RootDirectory +"..\\..\\..\\..\\..\\..\\SmokinAces\\Content\\" + filename);
                
                Texture_List.Add(tempText);
                index = Texture_List.IndexOf(tempText);
                FileName_Int.Add(filename, index);
                return index;
            }
        }
        public void add_Update_Object(Update_Delegate add)
        {
            UpdateObjects.Add(add);
        }
        public void remove_Update_Object(Update_Delegate remove)
        {
            UpdateObjects.Remove(remove);
        }
        public void add_Drawing_Object(String TextureFileName, Draw_Delegate method, Layers layernumber)
        {
            if (!Drawing_List[(int)layernumber].ContainsKey(TextureFileName))
            {
                Texture_List tempTL = new Texture_List(GraphicsDevice, TextureFileName, method);
                Drawing_List[(int)layernumber].Add(TextureFileName, tempTL);
            }
            else
            {
                Drawing_List[(int)layernumber][TextureFileName].Drawing_List.Add(method);
            }
        }
        public bool remove_Drawing_Object(String TextureFileName, Draw_Delegate method, Layers layernumber)
        {
            if (Drawing_List[(int)layernumber].ContainsKey(TextureFileName))
            {
                return Drawing_List[(int)layernumber][TextureFileName].Drawing_List.Remove(method);
            }
            return false;
        }

        protected void Draw_Lines(BoundingBox BoxToDraw)
        {
            VertexPositionColor[] Lines = new VertexPositionColor[5];
            Lines[0] = new VertexPositionColor(new Vector3(BoxToDraw.Min.X, BoxToDraw.Min.Y, 1.0f), SelectionColor);
            Lines[1] = new VertexPositionColor(new Vector3(BoxToDraw.Min.X, BoxToDraw.Max.Y, 1.0f), SelectionColor);
            Lines[2] = new VertexPositionColor(new Vector3(BoxToDraw.Max.X, BoxToDraw.Max.Y, 1.0f), SelectionColor);
            Lines[3] = new VertexPositionColor(new Vector3(BoxToDraw.Max.X, BoxToDraw.Min.Y, 1.0f), SelectionColor);
            Lines[4] = new VertexPositionColor(new Vector3(BoxToDraw.Min.X, BoxToDraw.Min.Y, 1.0f), SelectionColor);
            //---------Begin the drawing passes
            LineEffect.VertexColorEnabled = true;
            LineEffect.Begin();
            foreach (EffectPass pass in LineEffect.CurrentTechnique.Passes)
            {
                pass.Begin();
                GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineStrip, Lines, 0, 4);
                //GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indecies, 0, indecies.Length/3);
                pass.End();
            }
            LineEffect.End();
        }

        public bool loadFile()
        {
            OpenFileDialog fDialog = new OpenFileDialog();
            fDialog.Filter = "Saved Game:(*.sgxml)|*.sgxml";
            fDialog.DefaultExt = ".sgxml";
            fDialog.Multiselect = false;
            if (fDialog.ShowDialog() != DialogResult.OK)
            {
                return false;
            }
            XmlTextReader read = new XmlTextReader(fDialog.FileName);
            try
            {
                read.Read();
                read.ReadToFollowing("Map");
                string MapX = read.GetAttribute("XSize");
                string MapY = read.GetAttribute("YSize");

                if(read.ReadToFollowing("Hero"))
                {
                    string typeName = read.GetAttribute("Type");
                    Type objectType = Type.GetType(typeName);
                    Type[] listType = { typeof(XmlReader), typeof(SmokinAces.Main_Engine) };
                    ConstructorInfo builder = objectType.GetConstructor(listType);
                    XmlReader temp = read.ReadSubtree();
                    temp.Read();
                    object[] constParms = { temp, this };
                    SmokinAces.Game_Object tempObj = (SmokinAces.Game_Object)builder.Invoke(constParms);
                    Hero = (SmokinAces.Object_Classes.Objects.Main_Character)tempObj;
                }
                CurrentScreen.Min.X = (Hero.GraphicBB.Min.X + 32) - (GraphicsDevice.Viewport.Width / 2.0f);
                CurrentScreen.Max.X = (Hero.GraphicBB.Min.X + 32) + (GraphicsDevice.Viewport.Width / 2.0f);
                CurrentScreen.Min.Y = (Hero.GraphicBB.Min.Y + 32) - (GraphicsDevice.Viewport.Height / 2.0f);
                CurrentScreen.Max.Y = (Hero.GraphicBB.Min.Y + 32) + (GraphicsDevice.Viewport.Height / 2.0f);
                CurrentScreen.Min.Z = Util.MinZ;
                CurrentScreen.Max.Z = Util.MaxZ;
                List<Game_Object> NewCreations = new List<Game_Object>();
                while (read.ReadToFollowing("Game_Object"))
                {
                    string typeName = read.GetAttribute("Type");
                    Type objectType = Type.GetType(typeName);
                    Type[] listType = { typeof(XmlReader), typeof(SmokinAces.Main_Engine) };
                    ConstructorInfo builder = objectType.GetConstructor(listType);
                    XmlReader temp = read.ReadSubtree();
                    temp.Read();
                    object[] constParms = { temp, this };
                    SmokinAces.Game_Object tempObj = (SmokinAces.Game_Object)builder.Invoke(constParms);
                    NewCreations.Add(tempObj);
                }
                read.Close();
                NewMap(NewCreations, Convert.ToInt32(MapX), Convert.ToInt32(MapY));
                return true;
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Problems Loading File");
                read.Close();
                return false;
            }
        }
        private int Max_X;
        private int Max_Y;
        public void NewMap(List<Game_Object> objectList, int MaxX, int MaxY)
        {
            Max_X = MaxX;
            Max_Y = MaxY;
            //----------Build the Quadtree
            BoundingBox MapSize = new BoundingBox(new Vector3(0, 0, -1000.0f), new Vector3(MaxX, MaxY, 1000.0f));
            MapObjects = new Quadtree(MapSize);
            foreach (Game_Object iter in objectList)
            {
                this.MapObjects.Add(iter);
            }
        }
        public bool saveFile()
        {
            SaveFileDialog fDialog = new SaveFileDialog();
            fDialog.Filter = "Saved Game:(*.sgxml)|*.sgxml";
            fDialog.DefaultExt = ".sgxml";

            //OpenFileDialog fDialog = new OpenFileDialog();

            if (fDialog.ShowDialog() != DialogResult.OK)
            {
                return false;
            }
            try
            {
                XmlTextWriter write = new XmlTextWriter(fDialog.FileName, Encoding.Unicode);
                write.WriteStartDocument();
                write.WriteStartElement("Map");
                write.WriteAttributeString("XSize", Max_X.ToString());
                write.WriteAttributeString("YSize", Max_Y.ToString());
                if (Hero != null)
                {
                    Hero.Save_XML(write);
                }
                else
                {
                    Hero = new SmokinAces.Object_Classes.Objects.Main_Character(0, 0, this);
                    Hero.Save_XML(write);
                }
                foreach (SmokinAces.Game_Object iter in MapObjects.All_Objects())
                {
                    iter.Save_XML(write);
                }
                write.WriteEndElement();
                write.WriteEndDocument();
                write.Flush();
                write.Close();
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
